/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.mc.controller;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.xy.biz.mc.domain.bo.MessageBO;
import com.xy.biz.mc.domain.enums.MessageEndPointTypeEnum;
import com.xy.biz.mc.domain.req.*;
import com.xy.biz.mc.domain.resp.MessagePushResponse;
import com.xy.tool.context.UserContextHolder;
import com.xy.tool.util.BeanUtilsEx;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.xy.lang.domain.Page;
import com.xy.lang.domain.Result;
import com.xy.lang.validation.SaveChecks;
import com.xy.lang.validation.UpdateChecks;
import com.xy.lang.validation.annotation.Validatable;

import com.xy.biz.mc.domain.resp.GetMessageResponse;
import com.xy.biz.mc.domain.query.MessageQuery;
import com.xy.biz.mc.domain.converter.MessageConverter;
import com.xy.biz.mc.client.MessagePushClient;
import com.xy.biz.mc.service.MessageService;

/**
 *
 *
 * @author zsp
 * @date 2021-2-25
 */
@Slf4j
@RestController
@RequestMapping("/api/mc/message")
public class MessageController implements MessagePushClient {

	@Autowired
	private MessageService messageService;

	@Validatable(groups = {UpdateChecks.class})
	@PostMapping(value = "/update")
	public Result<?> updateMessage(@RequestBody SaveMessageRequest request) {
		messageService.updateMessage(MessageConverter.toBO(request));
		return Result.success();
	}

	@Deprecated
	@Validatable
	@PostMapping(value = "/delete")
	public Result<?> deleteMessage(@RequestBody GetMessageRequest request) {
		messageService.deleteMessage(request.getMessageId());
		return Result.success();
	}

	/**
	 * 删除多个
	 * @param request
	 * @return
	 */
	@Validatable
	@PostMapping(value = "/delete_multiple")
	public Result<?> deleteMessageMultiple(@RequestBody MultipleMessageRequest request) {
		return messageService.deleteMessageMultiple(request);
	}

	/**
	 * 标记已读
	 * @param request
	 * @return
	 */
	@Validatable
	@PostMapping(value = "/have_read_multiple")
	public Result<?> haveReadMultiple(@RequestBody MultipleMessageRequest request) {
		return messageService.haveReadMultiple(request);
	}

	@Deprecated
	@Validatable
	@PostMapping(value = "/get")
	public Result<GetMessageResponse> getMessage(@RequestBody GetMessageRequest request) {
		return Result.success(MessageConverter.toResponse(messageService.getMessage(request.getMessageId())));
	}

	@Deprecated
	@PostMapping(value = "/list_by_ids")
	public Result<List<GetMessageResponse>> listMessageById(@RequestBody Collection<Long> collection) {
		return Result.success(MessageConverter.toResponse(messageService.listMessageById(collection)));
	}

	@Deprecated
	@PostMapping(value = "/list")
	public Result<List<GetMessageResponse>> listMessage(@RequestBody ListMessageRequest request) {
		return Result.success(messageService.listMessage(MessageConverter.toQuery(request)));
	}

	@PostMapping(value = "/count")
	public Result<Integer> countMessage(@RequestBody CountMessageRequest request) {
		MessageQuery messageQuery = MessageConverter.toQuery(request);
		messageQuery.setToId(UserContextHolder.getUserId());
		return Result.success(messageService.countMessage(messageQuery));
	}

	@PostMapping(value = "/page")
	public Result<Page<GetMessageResponse>> pageMessage(@RequestBody ListMessageRequest request) {
		MessageQuery query = MessageConverter.toQuery(request);
		query.setToId(UserContextHolder.getUserId());
		int count = messageService.countMessage(query);
		List<GetMessageResponse> list;
		if (count == 0) {
			return Result.success(new Page<>(null, count));
		}
		list = messageService.listMessage(query);
		return Result.success(new Page<>(list, count));
	}

	@Deprecated
	@PostMapping(value = "/send")
	@Override
	public Result<MessagePushResponse> send(@RequestBody MessagePushRequest request) {
		MessageBO messageBO = createMessageBO(request, MessageEndPointTypeEnum.USER);
		return messageService.sendMessage(messageBO);
	}

	@Deprecated
	@PostMapping(value = "/send_to_group")
	@Override
	public Result<MessagePushResponse> sendToGroup(@RequestBody MessagePushRequest request) {
		MessageBO messageBO = createMessageBO(request, MessageEndPointTypeEnum.USER_GROUP);
		return messageService.sendMessage(messageBO);
	}

	@Deprecated
	@PostMapping(value = "/send_by_from")
	@Override
	public Result<MessagePushResponse> sendByFrom(@RequestBody MessagePushFromRequest request) {
		MessageBO messageBO = createMessageBO(request, MessageEndPointTypeEnum.USER);
		return messageService.sendMessage(messageBO);
	}

	@Deprecated
	@PostMapping(value = "/send_by_from_to_group")
	@Override
	public Result<MessagePushResponse> sendByFromToGroup(@RequestBody MessagePushFromRequest request) {
		MessageBO messageBO = createMessageBO(request, MessageEndPointTypeEnum.USER_GROUP);
		return messageService.sendMessage(messageBO);
	}

	@Deprecated
	@PostMapping(value = "/send_all")
	@Override
	public Result<MessagePushResponse> sendAll(@RequestBody Collection<MessagePushRequest> requests) {
		List<MessageBO> messageBOList = createMessageBO(requests, MessageEndPointTypeEnum.USER);
		return messageService.sendAllMessage(messageBOList);
	}

	@Deprecated
	@PostMapping(value = "/send_all_to_group")
	@Override
	public Result<MessagePushResponse> sendAllToGroup(@RequestBody Collection<MessagePushRequest> requests) {
		List<MessageBO> messageBOList = createMessageBO(requests, MessageEndPointTypeEnum.USER_GROUP);
		return messageService.sendAllMessage(messageBOList);
	}

	@Deprecated
	@PostMapping(value = "/send_all_by_from")
	@Override
	public Result<MessagePushResponse> sendAllByFrom(@RequestBody Collection<MessagePushFromRequest> requests) {
		List<MessageBO> messageBOList = createFromMessageBO(requests, MessageEndPointTypeEnum.USER);
		return messageService.sendAllMessage(messageBOList);
	}

	@Deprecated
	@PostMapping(value = "/send_all_by_from_to_group")
	@Override
	public Result<MessagePushResponse> sendAllByFromToGroup(@RequestBody Collection<MessagePushFromRequest> requests) {
		List<MessageBO> messageBOList = createFromMessageBO(requests, MessageEndPointTypeEnum.USER_GROUP);
		return messageService.sendAllMessage(messageBOList);
	}

	private MessageBO createMessageBO(MessagePushRequest request, MessageEndPointTypeEnum messageEndPointTypeEnum) {
		MessageBO messageBO = MessageBO.builder()
				.fromType(MessageEndPointTypeEnum.UNDEFINED.getCode())
				.fromId(0L)
				.toType(messageEndPointTypeEnum.getCode())
				.build();
		BeanUtilsEx.copyProperties(request, messageBO);
		if(messageBO.isOffline()) {
			messageBO.setExpiredTime(LocalDateTime.now().plusSeconds(request.getExpiredSeconds()));
		}
		return messageBO;
	}

	private List<MessageBO> createMessageBO(Collection<MessagePushRequest> requests,
											MessageEndPointTypeEnum messageEndPointTypeEnum ) {
		List<MessageBO> messageBOList = new ArrayList<>();
		if(!CollectionUtils.isEmpty(requests)) {
			MessageBO messageBO;
			for(MessagePushRequest request : requests) {
				messageBO = createMessageBO(request, messageEndPointTypeEnum);
				messageBOList.add(messageBO);
			}
		}
		return messageBOList;
	}

	private MessageBO createMessageBO(MessagePushFromRequest request, MessageEndPointTypeEnum messageEndPointTypeEnum) {
		MessageBO messageBO = MessageBO.builder()
				.fromType(MessageEndPointTypeEnum.USER.getCode())
				.toType(messageEndPointTypeEnum.getCode())
				.build();
		BeanUtilsEx.copyProperties(request, messageBO);
		if(messageBO.isOffline()) {
			messageBO.setExpiredTime(LocalDateTime.now().plusSeconds(request.getExpiredSeconds()));
		}
		return messageBO;
	}

	private List<MessageBO> createFromMessageBO(Collection<MessagePushFromRequest> requests,
												MessageEndPointTypeEnum messageEndPointTypeEnum ) {
		List<MessageBO> messageBOList = new ArrayList<>();
		if(!CollectionUtils.isEmpty(requests)) {
			MessageBO messageBO;
			for(MessagePushFromRequest request : requests) {
				messageBO = createMessageBO(request, messageEndPointTypeEnum);
				messageBOList.add(messageBO);
			}
		}
		return messageBOList;
	}

}
